﻿using Autofac;
using Microsoft.Extensions.DependencyModel;
using Microsoft.Extensions.Logging;
using CNative.Cloud.CPlatform.Cache;
using CNative.Cloud.CPlatform.Configurations;
using CNative.Cloud.CPlatform.Configurations.Watch;
using CNative.Cloud.CPlatform.Convertibles;
using CNative.Cloud.CPlatform.Convertibles.Implementation;
using CNative.Cloud.CPlatform.Engines;
using CNative.Cloud.CPlatform.Engines.Implementation;
using CNative.Cloud.CPlatform.EventBus.Events;
using CNative.Cloud.CPlatform.Filters;
using CNative.Cloud.CPlatform.Filters.Implementation;
using CNative.Cloud.CPlatform.HashAlgorithms;
using CNative.Cloud.CPlatform.Ids;
using CNative.Cloud.CPlatform.Ids.Implementation;
using CNative.Cloud.CPlatform.Ioc;
using CNative.Cloud.CPlatform.Module;
using CNative.Cloud.CPlatform.Mqtt;
using CNative.Cloud.CPlatform.Routing;
using CNative.Cloud.CPlatform.Routing.Implementation;
using CNative.Cloud.CPlatform.Runtime.Client;
using CNative.Cloud.CPlatform.Runtime.Client.Address.Resolvers;
using CNative.Cloud.CPlatform.Runtime.Client.Address.Resolvers.Implementation;
using CNative.Cloud.CPlatform.Runtime.Client.Address.Resolvers.Implementation.Selectors;
using CNative.Cloud.CPlatform.Runtime.Client.Address.Resolvers.Implementation.Selectors.Implementation;
using CNative.Cloud.CPlatform.Runtime.Client.HealthChecks;
using CNative.Cloud.CPlatform.Runtime.Client.HealthChecks.Implementation;
using CNative.Cloud.CPlatform.Runtime.Client.Implementation;
using CNative.Cloud.CPlatform.Runtime.Server;
using CNative.Cloud.CPlatform.Runtime.Server.Implementation;
using CNative.Cloud.CPlatform.Runtime.Server.Implementation.ServiceDiscovery;
using CNative.Cloud.CPlatform.Runtime.Server.Implementation.ServiceDiscovery.Attributes;
using CNative.Cloud.CPlatform.Runtime.Server.Implementation.ServiceDiscovery.Implementation;
using CNative.Cloud.CPlatform.Serialization;
using CNative.Cloud.CPlatform.Serialization.Implementation;
using CNative.Cloud.CPlatform.Support;
using CNative.Cloud.CPlatform.Support.Implementation;
using CNative.Cloud.CPlatform.Transport.Codec;
using CNative.Cloud.CPlatform.Transport.Codec.Implementation;
using CNative.Cloud.CPlatform.Utilities;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;
using Autofac.Core;
using Microsoft.Extensions.DependencyInjection;
using CNative.Cloud.CPlatform.Exceptions;

namespace CNative.Cloud.CPlatform
{
    /// <summary>
    /// 服务构建者。
    /// </summary>
    public interface IServiceBuilder
    {
        /// <summary>
        /// 服务集合。
        /// </summary>
        ContainerBuilder Services { get; }
    }

    /// <summary>
    /// 默认服务构建者。
    /// </summary>
    internal sealed class ServiceBuilder : IServiceBuilder
    {
        private ServiceBuilder(ContainerBuilder services)
        {
            if (services == null)
                throw new ArgumentNullException(nameof(services));
            Services = services;
        }

        private static ServiceBuilder _instance;

        public static ServiceBuilder CreateServiceBuilder(ContainerBuilder builder)
        {
            _instance = new ServiceBuilder(builder);

            return _instance;
        }


        #region Implementation of IServiceBuilder

        /// <summary>
        /// 服务集合。
        /// </summary>
        public ContainerBuilder Services { get; private set; }

        #endregion Implementation of IServiceBuilder
    }

    public static class ContainerBuilderExtensions
    {
        private static List<Assembly> _referenceAssembly = new List<Assembly>();
        private static List<AbstractModule> _modules = new List<AbstractModule>();

        public static List<Assembly> ReferenceAssembly => _referenceAssembly;

        /// <summary>
        /// 添加Json序列化支持。
        /// </summary>
        /// <param name="builder">服务构建者。</param>
        /// <returns>服务构建者。</returns>
        public static IServiceBuilder AddJsonSerialization(this IServiceBuilder builder)
        {
            var services = builder.Services;
            services.RegisterType(typeof(JsonSerializer)).As(typeof(ISerializer<string>)).SingleInstance();
            services.RegisterType(typeof(StringByteArraySerializer)).As(typeof(ISerializer<byte[]>)).SingleInstance();
            services.RegisterType(typeof(StringObjectSerializer)).As(typeof(ISerializer<object>)).SingleInstance();
            return builder;
        }
        #region RouteManager

        /// <summary>
        /// 设置服务路由管理者。
        /// </summary>
        /// <typeparam name="T">服务路由管理者实现。</typeparam>
        /// <param name="builder">服务构建者。</param>
        /// <returns>服务构建者。</returns>
        public static IServiceBuilder UseRouteManager<T>(this IServiceBuilder builder) where T : class, IServiceRouteManager
        {
            builder.Services.RegisterType(typeof(T)).As(typeof(IServiceRouteManager)).SingleInstance();
            return builder;
        }

        /// <summary>
        /// 设置服务路由管理者。
        /// </summary>
        /// <param name="builder">服务构建者。</param>
        /// <param name="factory">服务路由管理者实例工厂。</param>
        /// <returns>服务构建者。</returns>
        public static IServiceBuilder UseRouteManager(this IServiceBuilder builder, Func<IServiceProvider, IServiceRouteManager> factory)
        {
            builder.Services.RegisterAdapter(factory).SingleInstance();
            return builder;
        }

        /// <summary>
        /// 设置服务订阅管理者。
        /// </summary>
        /// <param name="builder">服务构建者。</param>
        /// <param name="factory">服务订阅管理者实例工厂。</param>
        /// <returns>服务构建者。</returns>
        public static IServiceBuilder UseSubscribeManager(this IServiceBuilder builder, Func<IServiceProvider, IServiceSubscribeManager> factory)
        {
            builder.Services.RegisterAdapter(factory).SingleInstance();
            return builder;
        }

        /// <summary>
        /// 设置服务命令管理者。
        /// </summary>
        /// <param name="builder">服务构建者。</param>
        /// <param name="factory">服务命令管理者实例工厂。</param>
        /// <returns>服务构建者。</returns>
        public static IServiceBuilder UseCommandManager(this IServiceBuilder builder, Func<IServiceProvider, IServiceCommandManager> factory)
        {
            builder.Services.RegisterAdapter(factory).SingleInstance();
            return builder;
        }

        /// <summary>
        /// 设置缓存管理者。
        /// </summary>
        /// <param name="builder">服务构建者。</param>
        /// <param name="factory">缓存管理者实例工厂。</param>
        /// <returns>服务构建者。</returns>
        public static IServiceBuilder UseCacheManager(this IServiceBuilder builder, Func<IServiceProvider, IServiceCacheManager> factory)
        {
            builder.Services.RegisterAdapter(factory).SingleInstance();
            return builder;
        }

        /// <summary>
        /// 设置服务路由管理者。
        /// </summary>
        /// <param name="builder">服务构建者。</param>
        /// <param name="instance">服务路由管理者实例。</param>
        /// <returns>服务构建者。</returns>
        public static IServiceBuilder UseRouteManager(this IServiceBuilder builder, IServiceRouteManager instance)
        {
            builder.Services.RegisterInstance(instance);
            return builder;
        }

        /// <summary>
        /// 设置mqtt服务路由管理者。
        /// </summary>
        /// <param name="builder">mqtt服务构建者。</param>
        /// <param name="factory">mqtt服务路由管理者实例工厂。</param>
        /// <returns>服务构建者。</returns>
        public static IServiceBuilder UseMqttRouteManager(this IServiceBuilder builder, Func<IServiceProvider, IMqttServiceRouteManager> factory)
        {
            builder.Services.RegisterAdapter(factory).SingleInstance();
            return builder;
        }

        #endregion RouteManager


        #region AddressSelector
        /// <summary>
        /// 使用轮询的地址选择器。
        /// </summary>
        /// <param name="builder">服务构建者。</param>
        /// <returns>服务构建者。</returns>
        public static IServiceBuilder UsePollingAddressSelector(this IServiceBuilder builder)
        {
            builder.Services.RegisterType(typeof(PollingAddressSelector))
                .Named(AddressSelectorMode.Polling.ToString(), typeof(IAddressSelector)).SingleInstance();
            return builder;
        }

        /// <summary>
        /// 使用压力最小优先分配轮询的地址选择器。
        /// </summary>
        /// <param name="builder">服务构建者。</param>
        /// <returns>服务构建者。</returns>
        public static IServiceBuilder UseFairPollingAddressSelector(this IServiceBuilder builder)
        {
            builder.Services.RegisterType(typeof(FairPollingAdrSelector))
                .Named(AddressSelectorMode.FairPolling.ToString(), typeof(IAddressSelector)).SingleInstance();
            return builder;
        }

        /// <summary>
        /// 使用哈希的地址选择器。
        /// </summary>
        /// <param name="builder">服务构建者。</param>
        /// <returns>服务构建者。</returns>
        public static IServiceBuilder UseHashAlgorithmAddressSelector(this IServiceBuilder builder)
        {
            builder.Services.RegisterType(typeof(HashAlgorithmAdrSelector))
                .Named(AddressSelectorMode.HashAlgorithm.ToString(), typeof(IAddressSelector)).SingleInstance();
            return builder;
        }

        /// <summary>
        /// 使用随机的地址选择器。
        /// </summary>
        /// <param name="builder">服务构建者。</param>
        /// <returns>服务构建者。</returns>
        public static IServiceBuilder UseRandomAddressSelector(this IServiceBuilder builder)
        {
            builder.Services.RegisterType(typeof(RandomAddressSelector))
                .Named(AddressSelectorMode.Random.ToString(), typeof(IAddressSelector)).SingleInstance();
            return builder;
        }

        /// <summary>
        /// 设置服务地址选择器。
        /// </summary>
        /// <param name="builder">服务构建者。</param>
        /// <param name="instance">地址选择器实例。</param>
        /// <returns>服务构建者。</returns>
        public static IServiceBuilder UseAddressSelector(this IServiceBuilder builder)
        {
            return builder.UseRandomAddressSelector().UsePollingAddressSelector().UseFairPollingAddressSelector().UseHashAlgorithmAddressSelector();
        }

        #endregion AddressSelector

        #region Configuration Watch

        /// <summary>
        /// Configuration Watch
        /// </summary>
        /// <param name="builder"></param>
        /// <returns>服务构建者</returns>
        public static IServiceBuilder AddConfigurationWatch(this IServiceBuilder builder)
        {
            var services = builder.Services;
            services.RegisterType(typeof(ConfigurationWatchManager)).As(typeof(IConfigurationWatchManager)).SingleInstance();
            return builder;
        }
        #endregion

        #region Codec Factory

        /// <summary>
        /// 使用编解码器。
        /// </summary>
        /// <param name="builder">服务构建者。</param>
        /// <param name="codecFactory"></param>
        /// <returns>服务构建者。</returns>
        public static IServiceBuilder UseCodec(this IServiceBuilder builder, ITransportMessageCodecFactory codecFactory)
        {
            builder.Services.RegisterInstance(codecFactory).SingleInstance();
            return builder;
        }

        /// <summary>
        /// 使用编解码器。
        /// </summary>
        /// <typeparam name="T">编解码器工厂实现类型。</typeparam>
        /// <param name="builder">服务构建者。</param>
        /// <returns>服务构建者。</returns>
        public static IServiceBuilder UseCodec<T>(this IServiceBuilder builder) where T : class, ITransportMessageCodecFactory
        {
            builder.Services.RegisterType(typeof(T)).As(typeof(ITransportMessageCodecFactory)).SingleInstance();
            return builder;
        }

        /// <summary>
        /// 使用编解码器。
        /// </summary>
        /// <param name="builder">服务构建者。</param>
        /// <param name="codecFactory">编解码器工厂创建委托。</param>
        /// <returns>服务构建者。</returns>
        public static IServiceBuilder UseCodec(this IServiceBuilder builder, Func<IServiceProvider, ITransportMessageCodecFactory> codecFactory)
        {
            builder.Services.RegisterAdapter(codecFactory).SingleInstance();
            return builder;
        }

        #endregion Codec Factory

        public static IServiceBuilder GetServiceBuilder(this ContainerBuilder containerBuilder)
        {
            return ServiceBuilder.CreateServiceBuilder(containerBuilder);
        }

        /// <summary>
        /// 使用Json编解码器。
        /// </summary>
        /// <param name="builder">服务构建者。</param>
        /// <returns>服务构建者。</returns>
        public static IServiceBuilder UseJsonCodec(this IServiceBuilder builder)
        {
            return builder.UseCodec<JsonTransportMessageCodecFactory>();
        }

        /// <summary>
        /// 添加客户端运行时服务。
        /// </summary>
        /// <param name="builder">服务构建者。</param>
        /// <returns>服务构建者。</returns>
        public static IServiceBuilder AddClientRuntime(this IServiceBuilder builder)
        {
            var services = builder.Services;
            services.RegisterType(typeof(DefaultHealthCheckService)).As(typeof(IHealthCheckService)).SingleInstance();
            services.RegisterType(typeof(DefaultAddressResolver)).As(typeof(IAddressResolver)).SingleInstance();
            services.RegisterType(typeof(RemoteInvokeService)).As(typeof(IRemoteInvokeService)).SingleInstance();
            return builder.UseAddressSelector().AddClusterSupport();
        }

        /// <summary>
        /// 添加集群支持
        /// </summary>
        /// <param name="builder">服务构建者</param>
        /// <returns>服务构建者。</returns>
        public static IServiceBuilder AddClusterSupport(this IServiceBuilder builder)
        {
            var services = builder.Services;
            services.RegisterType(typeof(ServiceCommandProvider)).As(typeof(IServiceCommandProvider)).SingleInstance();
            services.RegisterType(typeof(BreakeRemoteInvokeService)).As(typeof(IBreakeRemoteInvokeService)).SingleInstance();
            services.RegisterType(typeof(FailoverInjectionInvoker)).AsImplementedInterfaces()
                .Named(StrategyType.Injection.ToString(), typeof(IClusterInvoker)).SingleInstance();
            services.RegisterType(typeof(FailoverHandoverInvoker)).AsImplementedInterfaces()
            .Named(StrategyType.Failover.ToString(), typeof(IClusterInvoker)).SingleInstance();
            return builder;
        }

        public static IServiceBuilder AddFilter(this IServiceBuilder builder, IFilter filter)
        {
            var services = builder.Services;
            services.Register(p => filter).As(typeof(IFilter)).SingleInstance();
            if (typeof(IExceptionFilter).IsAssignableFrom(filter.GetType()))
            {
                var exceptionFilter = filter as IExceptionFilter;
                services.Register(p => exceptionFilter).As(typeof(IExceptionFilter)).SingleInstance();
            }
            else if (typeof(IAuthorizationFilter).IsAssignableFrom(filter.GetType()))
            {
                var authorizationFilter = filter as IAuthorizationFilter;
                services.Register(p => authorizationFilter).As(typeof(IAuthorizationFilter)).SingleInstance();
            }
            return builder;
        }

        public static IServiceBuilder AddServiceEngine(this IServiceBuilder builder, Type engine)
        {
            var services = builder.Services;
            services.RegisterType(engine).As(typeof(IServiceEngine)).SingleInstance();
            builder.Services.RegisterType(typeof(DefaultServiceEngineBuilder)).As(typeof(IServiceEngineBuilder)).SingleInstance();
            return builder;
        }

        /// <summary>
        /// 添加服务运行时服务。
        /// </summary>
        /// <param name="builder">服务构建者。</param>
        /// <returns>服务构建者。</returns>
        public static IServiceBuilder AddServiceRuntime(this IServiceBuilder builder)
        {
            builder.Services.RegisterType(typeof(DefaultServiceEntryLocate)).As(typeof(IServiceEntryLocate)).SingleInstance();
            builder.Services.RegisterType(typeof(DefaultServiceExecutor)).As(typeof(IServiceExecutor))
                .Named<IServiceExecutor>(CommunicationProtocol.Tcp.ToString()).SingleInstance();
            return builder
                .AddCoreService()
                .RegisterServices()
                .RegisterRepositories()
                .RegisterServiceBus()
                .RegisterModules()
                .RegisterInstanceByConstraint()
                .AddRuntime()
                //.RegisterFodlerServices()
                .RegisterModulesAndComponents()
                ;
        }

        /// <summary>
        /// 添加关联服务运行时 
        /// </summary>
        /// <param name="builder">服务构建者。</param>
        /// <returns>服务构建者。</returns>
        public static IServiceBuilder AddRelateServiceRuntime(this IServiceBuilder builder)
        {
            var services = builder.Services;
            services.RegisterType(typeof(DefaultHealthCheckService)).As(typeof(IHealthCheckService)).SingleInstance();
            services.RegisterType(typeof(DefaultAddressResolver)).As(typeof(IAddressResolver)).SingleInstance();
            services.RegisterType(typeof(RemoteInvokeService)).As(typeof(IRemoteInvokeService)).SingleInstance();
            return builder.UseAddressSelector().AddClusterSupport();
        }

        /// <summary>
        /// 添加核心服务。
        /// </summary>
        /// <param name="builder">服务集合。</param>
        /// <returns>服务构建者。</returns>
        public static IServiceBuilder AddCoreService(this IServiceBuilder builder)
        {
            Check.NotNull(builder, "builder");
            //注册服务ID生成实例 
            builder.Services.RegisterType<DefaultServiceIdGenerator>().As<IServiceIdGenerator>().SingleInstance();
            builder.Services.Register(p =>
            {
                var context = p.Resolve<IComponentContext>();
                return new CPlatformContainer(context);
            });
            //注册默认的类型转换 
            builder.Services.RegisterType(typeof(DefaultTypeConvertibleProvider)).As(typeof(ITypeConvertibleProvider)).SingleInstance();
            //注册默认的类型转换服务 
            builder.Services.RegisterType(typeof(DefaultTypeConvertibleService)).As(typeof(ITypeConvertibleService)).SingleInstance();
            //注册权限过滤 
            builder.Services.RegisterType(typeof(AuthorizationAttribute)).As(typeof(IAuthorizationFilter)).SingleInstance();
            //注册基本过滤 
            builder.Services.RegisterType(typeof(AuthorizationAttribute)).As(typeof(IFilter)).SingleInstance();
            //注册服务器路由接口 
            builder.Services.RegisterType(typeof(DefaultServiceRouteProvider)).As(typeof(IServiceRouteProvider)).SingleInstance();
            //注册服务路由工厂 
            builder.Services.RegisterType(typeof(DefaultServiceRouteFactory)).As(typeof(IServiceRouteFactory)).SingleInstance();
            //注册服务订阅工厂 
            builder.Services.RegisterType(typeof(DefaultServiceSubscriberFactory)).As(typeof(IServiceSubscriberFactory)).SingleInstance();
            //注册服务token生成接口 
            builder.Services.RegisterType(typeof(ServiceTokenGenerator)).As(typeof(IServiceTokenGenerator)).SingleInstance();
            //注册哈希一致性算法 
            builder.Services.RegisterType(typeof(HashAlgorithm)).As(typeof(IHashAlgorithm)).SingleInstance();
            //注册组件生命周期接口 
            builder.Services.RegisterType(typeof(ServiceEngineLifetime)).As(typeof(IServiceEngineLifetime)).SingleInstance();
            //注册服务心跳管理 
            builder.Services.RegisterType(typeof(DefaultServiceHeartbeatManager)).As(typeof(IServiceHeartbeatManager)).SingleInstance();
            return builder
                .AddJsonSerialization()
                .UseJsonCodec();
        }

        public static IServiceBuilder RegisterInstanceByConstraint(this IServiceBuilder builder, params string[] virtualPaths)
        {
            var services = builder.Services;
            var referenceAssemblies = GetReferenceAssembly(virtualPaths);

            foreach (var assembly in referenceAssemblies)
            {
                services.RegisterAssemblyTypes(assembly)
                 .Where(t => typeof(ISingletonDependency).GetTypeInfo().IsAssignableFrom(t)).AsImplementedInterfaces().AsSelf().SingleInstance();

                services.RegisterAssemblyTypes(assembly)
                .Where(t => typeof(ITransientDependency).GetTypeInfo().IsAssignableFrom(t)).AsImplementedInterfaces().AsSelf().InstancePerDependency();
            }
            return builder;

        }
        /// <summary>
        /// 动态添加 业务模块和组件模块
        /// </summary>
        /// <param name="serviceBuilder"></param>
        /// <returns></returns>
        public static IServiceBuilder RegisterModulesAndComponents(this IServiceBuilder serviceBuilder)
        {
            if (!string.IsNullOrEmpty(CPlatform.AppConfig.ServerOptions.AddOnsRootPath))
            {
                var paths = GetPaths(CPlatform.AppConfig.ServerOptions.AddOnsRootPath);
                if (paths != null)
                {
                    ConsoleC.WriteLine($"准备加载路径${string.Join(",", paths)}下的附加组件。", ConsoleColor.DarkBlue);
                    var services = serviceBuilder.Services;
                    var referenceAssemblies = GetAssemblies(paths);
                    //foreach (var assembly in referenceAssemblies)
                    {
                        try
                        {
                            services.RegisterAssemblyTypes(referenceAssemblies?.ToArray());
                            //services.RegisterAssemblyTypes(assembly);
                        }
                        catch (Exception ex)
                        {
                            ConsoleC.WriteLine(ex, "RegisterModulesAndComponents（） error ");
                        }
                    }
                }
            }
            //-------------------------------------------------------------------------------------------------------------------
            if (!string.IsNullOrEmpty(CPlatform.AppConfig.ServerOptions.ComponentsRootPath))
            {
                var paths = GetPaths(CPlatform.AppConfig.ServerOptions.ComponentsRootPath);
                if (paths != null)
                {
                    ConsoleC.WriteLine($"准备加载路径${string.Join(",", paths)}下的组件模块。", ConsoleColor.DarkCyan);
                    serviceBuilder.RegisterModules(paths);
                }
            }
            //-------------------------------------------------------------------------------------------------------------------
            if (!string.IsNullOrEmpty(CPlatform.AppConfig.ServerOptions.ModulesRootPath))
            {
                var paths = GetPaths(CPlatform.AppConfig.ServerOptions.ModulesRootPath);
                if (paths != null)
                {
                    ConsoleC.WriteLine($"准备加载路径${string.Join(",", paths)}下的业务模块。", ConsoleColor.DarkMagenta);
                    serviceBuilder.RegisterServices(paths);
                    serviceBuilder.RegisterRepositories(paths);
                    serviceBuilder.RegisterServiceBus(paths);
                    serviceBuilder.RegisterInstanceByConstraint(paths);
                }
            }

            return serviceBuilder;
        }
        ///// <summary>
        ///// 动态添加服务
        ///// </summary>
        ///// <param name="builder"></param>
        ///// <returns></returns>
        //public static IServiceBuilder RegisterFodlerServices(this IServiceBuilder builder)
        //{
        //    var services = builder.Services;

        //    var paths = GetPaths(new string[] { CPlatform.AppConfig.ServerOptions.ModulesRootPath });
        //    //动态添加服务
        //    if (paths != null)
        //    {
        //        ConsoleC.WriteLine($"准备加载路径${string.Join(",", paths)}下的动态添加服务模块。", ConsoleColor.DarkBlue);
        //        var assemblysc = GetReferenceAssembly(paths);
        //        if (assemblysc?.Count > 0)
        //        {
        //            assemblysc.ForEach(assembly =>
        //            {
        //                // var assembly = assemblysc.ToArray();
        //                services.RegisterAssemblyTypes(assembly)
        //                     //注入继承IServiceKey接口的所有接口
        //                     .Where(t => typeof(IServiceKey).GetTypeInfo().IsAssignableFrom(t) && t.IsInterface)
        //                     .AsImplementedInterfaces();

        //                services.RegisterAssemblyTypes(assembly)
        //                //注入实现IServiceBehavior接口并ServiceBundle不为空的类，作为接口实现类
        //                .Where(t => typeof(IServiceBehavior).GetTypeInfo().IsAssignableFrom(t)).AsImplementedInterfaces();

        //                //依赖注入仓储模块程序集
        //                services.RegisterAssemblyTypes(assembly)
        //                .Where(t => typeof(BaseRepository).GetTypeInfo().IsAssignableFrom(t));

        //                //var types = assembly.GetTypes().Where(t => typeof(IServiceBehavior).GetTypeInfo().IsAssignableFrom(t) && t.GetTypeInfo().GetCustomAttribute<ServiceBundleAttribute>() != null);
        //                //foreach (var type in types)
        //                //{
        //                //    var module = type.GetTypeInfo().GetCustomAttribute<ServiceBundleAttribute>();
        //                //    //对ModuleName不为空的对象，找到第一个继承IServiceKey的接口并注入接口及实现
        //                //    var interfaceObj = type.GetInterfaces()
        //                //        .FirstOrDefault(t => typeof(IServiceKey).GetTypeInfo().IsAssignableFrom(t));
        //                //    if (interfaceObj != null)
        //                //    {
        //                //        services.RegisterType(type).AsImplementedInterfaces().Named(type.FullName, interfaceObj);
        //                //        services.RegisterType(type).Named(type.FullName, type);
        //                //    }
        //                //}
        //            });
        //        }
        //    }
        //    return builder;
        //}

        private static IServiceBuilder AddRuntime(this IServiceBuilder builder)
        {
            var services = builder.Services;

            services.RegisterType(typeof(ClrServiceEntryFactory)).As(typeof(IClrServiceEntryFactory)).SingleInstance();
            services.Register(provider =>
            {
                try
                {
                    var _serviceProvider = provider.Resolve<CPlatformContainer>();
                    // builder.RegisterFodlerServices(_serviceProvider);


                    var assemblys = GetReferenceAssembly();

                    var types = assemblys.SelectMany(i => i.ExportedTypes).ToArray();
                    return new AttributeServiceEntryProvider(types, provider.Resolve<IClrServiceEntryFactory>(),
                        provider.Resolve<ILogger<AttributeServiceEntryProvider>>(), _serviceProvider);

                }
                finally
                {
                    //  builder = null;
                }
            }).As<IServiceEntryProvider>().SingleInstance();
            builder.Services.RegisterType(typeof(DefaultServiceEntryManager)).As(typeof(IServiceEntryManager)).SingleInstance();
            return builder;
        }

        private static string[] GetPaths(params string[] virtualPaths)
        {
            var directories = new List<string>(virtualPaths.Where(p => !string.IsNullOrEmpty(p)));
            string rootPath = string.IsNullOrEmpty(AppConfig.ServerOptions.RootPath) ?
                Cloud.CPlatform.Utilities.EnvironmentHelper.BaseDirectory : AppConfig.ServerOptions.RootPath;
            var virPaths = virtualPaths;
            foreach (var virtualPath in virtualPaths)
            {
                var path = Path.Combine(rootPath, virtualPath);
                //if (_logger.IsEnabled(LogLevel.Debug))
                //    _logger.LogDebug($"准备查找路径{path}下的目录。");
                if (Directory.Exists(path))
                {
                    var dirs = Directory.GetDirectories(path);
                    directories.AddRange(dirs.Select(dir => Path.Combine(virtualPath, new DirectoryInfo(dir).Name)));
                }
                else
                {
                    //  if (_logger.IsEnabled(LogLevel.Debug))
                    //      _logger.LogDebug($"未找到路径：{path}。");
                    directories.Remove(virtualPath);
                    virPaths = null;
                }
            }
            return directories.Any() ? directories.Distinct().ToArray() : virPaths;
        }

        /// <summary>.
        /// 依赖注入业务模块程序集
        /// </summary>
        /// <param name="builder">ioc容器</param>
        /// <returns>返回注册模块信息</returns>
        public static IServiceBuilder RegisterServices(this IServiceBuilder builder, params string[] virtualPaths)
        {
            try
            {
#if NET461
                HashSet<Type> htypes = new HashSet<Type>();
#endif
                var services = builder.Services;
                var referenceAssemblies = GetAssemblies(virtualPaths);
                foreach (var assembly in referenceAssemblies)
                {
                    try
                    {
                        services.RegisterAssemblyTypes(assembly)
                          //注入继承IServiceKey接口的所有接口
                          .Where(t => typeof(IServiceKey).GetTypeInfo().IsAssignableFrom(t) && t.IsInterface)
                          .AsImplementedInterfaces();

                        services.RegisterAssemblyTypes(assembly)
                         //注入实现IServiceBehavior接口并ModuleName为空的类，作为接口实现类
                         .Where(t => typeof(IServiceBehavior).GetTypeInfo().IsAssignableFrom(t) && t.GetTypeInfo().GetCustomAttribute<ModuleNameAttribute>() == null)
                         .AsImplementedInterfaces();

                        var types = assembly.GetTypes().Where(t => typeof(IServiceBehavior).GetTypeInfo().IsAssignableFrom(t) && t.GetTypeInfo().GetCustomAttribute<ModuleNameAttribute>() != null);
                        foreach (var type in types)
                        {
                            var module = type.GetTypeInfo().GetCustomAttribute<ModuleNameAttribute>();
                            //对ModuleName不为空的对象，找到第一个继承IServiceKey的接口并注入接口及实现
                            var interfaceObj = type.GetInterfaces()
                                .FirstOrDefault(t => typeof(IServiceKey).GetTypeInfo().IsAssignableFrom(t));
                            if (interfaceObj != null)
                            {
                                services.RegisterType(type).AsImplementedInterfaces().Named(module.ModuleName, interfaceObj);
                                services.RegisterType(type).Named(module.ModuleName, type);
                            }
                        }
#if NET461
                        //------------------------------------------------------------------------------------------------------
                        if (!string.IsNullOrEmpty(CPlatform.AppConfig.ServerOptions.WcfUsingServices))
                        {
                            services.RegisterAssemblyTypes(assembly)
                             //注入继承IServiceKey接口的所有接口
                             .Where(t => AppConfig.ServerOptions.WcfUsingServices.ToLower().Contains(t.Name.ToLower()) == true 
                                && t.GetTypeInfo().GetCustomAttribute<System.ServiceModel.ServiceContractAttribute>() != null && t.IsInterface)
                             .AsImplementedInterfaces();

                            var typess = assembly.GetTypes().Where(t => AppConfig.ServerOptions.WcfUsingServices.ToLower().Contains(t.Name.ToLower()) 
                                && t.IsInterface && t.GetTypeInfo().GetCustomAttribute<System.ServiceModel.ServiceContractAttribute>() != null);
                            foreach (var type in typess) htypes.Add(type);
                        }
#endif
                    }
                    catch (Exception ex)
                    {
                        if (ex is System.Reflection.ReflectionTypeLoadException typeLoadException)
                        {
                            var loaderExceptions = typeLoadException.LoaderExceptions;
                            throw loaderExceptions[0];
                        }
                        throw ex;
                    }
                }

#if NET461
                //------------------------------------------------------------------------------------------------------
                foreach (var type in htypes)
                {
                    if (type == null) continue;
                    foreach (var assembly in referenceAssemblies)
                    {
                        try
                        {
                            services.RegisterAssemblyTypes(assembly)
                             //注入实现IServiceBehavior接口并ModuleName为空的类，作为接口实现类
                             .Where(t => type.GetTypeInfo().IsAssignableFrom(t))
                             .AsImplementedInterfaces();
                        }
                        catch (Exception ex)
                        {
                            ConsoleC.WriteLine(ex);
                        }
                    }
                }
#endif
                return builder;
            }
            catch (Exception ex)
            {
                if (ex is System.Reflection.ReflectionTypeLoadException typeLoadException)
                {
                    var loaderExceptions = typeLoadException.LoaderExceptions;
                    throw loaderExceptions[0];
                }
                throw ex;
            }
        }

        /// <summary>
        /// 依赖注入事件总线模块程序集 
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="virtualPaths"></param>
        /// <returns>返回注册模块信息</returns>
        public static IServiceBuilder RegisterServiceBus
            (this IServiceBuilder builder, params string[] virtualPaths)
        {
            var services = builder.Services;
            var referenceAssemblies = GetAssemblies(virtualPaths);

            foreach (var assembly in referenceAssemblies)
            {
                services.RegisterAssemblyTypes(assembly)
                 .Where(t => typeof(IIntegrationEventHandler).GetTypeInfo().IsAssignableFrom(t)).AsImplementedInterfaces().SingleInstance();
                services.RegisterAssemblyTypes(assembly)
                 .Where(t => typeof(IIntegrationEventHandler).IsAssignableFrom(t)).SingleInstance();
            }
            return builder;
        }

        ///  <summary>
        /// 依赖注入仓储模块程序集
        ///  </summary>
        ///  <param name="builder">IOC容器</param>
        /// <param name="virtualPaths">虚拟路径</param>
        /// <returns>返回注册模块信息</returns>
        public static IServiceBuilder RegisterRepositories(this IServiceBuilder builder, params string[] virtualPaths)
        {
            var services = builder.Services;
            var referenceAssemblies = GetAssemblies(virtualPaths);

            foreach (var assembly in referenceAssemblies)
            {
                services.RegisterAssemblyTypes(assembly)
                    .Where(t => typeof(BaseRepository).GetTypeInfo().IsAssignableFrom(t));
            }
            return builder;
        }

        /// <summary>
        /// 依赖注入组件模块程序集
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="virtualPaths"></param>
        /// <returns>返回注册模块信息</returns>
        public static IServiceBuilder RegisterModules(this IServiceBuilder builder, params string[] virtualPaths)
        {
            var services = builder.Services;
            var referenceAssemblies = GetAssemblies(virtualPaths);
            if (builder == null) throw new ArgumentNullException("builder");
            //从CNativeSettings.json取到packages
            var packages = ConvertDictionary(AppConfig.ServerOptions.Packages);
            foreach (var moduleAssembly in referenceAssemblies)
            {
                GetAbstractModules(moduleAssembly).ForEach(p =>
                {
                    services.RegisterModule(p);
                    if (packages.ContainsKey(p.TypeName))
                    {
                        var useModules = packages[p.TypeName];
                        if (useModules?.ToLower().Contains(p.ModuleName?.ToLower()) == true)
                            //if (useModules.AsSpan().IndexOf(p.ModuleName) >= 0)
                            p.Enable = true;
                        else
                            p.Enable = false;
                    }
                    _modules.Add(p);
                });
            }
            builder.Services.Register(provider => new ModuleProvider(
               _modules, virtualPaths, provider.Resolve<ILogger<ModuleProvider>>()
                )).As<IModuleProvider>().SingleInstance();
            return builder;
        }

        public static List<Type> GetInterfaceService(this IServiceBuilder builder, params string[] virtualPaths)
        {
            var types = new List<Type>();
            var referenceAssemblies = GetReferenceAssembly(virtualPaths);
            referenceAssemblies.ForEach(p =>
            {
                types.AddRange(p.GetTypes().Where(t => typeof(IServiceKey).GetTypeInfo().IsAssignableFrom(t) && t.IsInterface));
            });
            return types;
        }

        public static IEnumerable<string> GetDataContractName(this IServiceBuilder builder, params string[] virtualPaths)
        {
            var namespaces = new List<string>();
            var assemblies = builder.GetInterfaceService(virtualPaths)
                .Select(p => p.Assembly)
                .Union(GetSystemModules())
                .Distinct()
                .ToList();

            assemblies.ForEach(assembly =>
            {
                namespaces.AddRange(assembly.GetTypes().Where(t => t.GetCustomAttribute<DataContractAttribute>() != null).Select(n => n.Namespace));
            });
            return namespaces;
        }

        private static IDictionary<string, string> ConvertDictionary(List<ModulePackage> list)
        {
            var result = new Dictionary<string, string>();
            list.ForEach(p =>
            {
                result.Add(p.TypeName, p.Using);
            });
            return result;
        }

        private static List<Assembly> GetReferenceAssembly(params string[] virtualPaths)
        {
            var refAssemblies = new List<Assembly>();
            var rootPath = Cloud.CPlatform.Utilities.EnvironmentHelper.BaseDirectory;
            var existsPath = virtualPaths.Any();
            if (existsPath && !string.IsNullOrEmpty(AppConfig.ServerOptions.RootPath))
                rootPath = AppConfig.ServerOptions.RootPath;
            var result = _referenceAssembly;
            if (!result.Any() || existsPath)
            {
                var paths = virtualPaths.Select(m => Path.Combine(rootPath, m)).ToList();
                if (!existsPath) paths.Add(rootPath);
                paths.ForEach(path =>
                {
                    var assemblyFiles = GetAllAssemblyFiles(path);

                    foreach (var referencedAssemblyFile in assemblyFiles)
                    {
                        try
                        {
                            var referencedAssembly = Assembly.LoadFrom(referencedAssemblyFile);
                            if (!_referenceAssembly.Contains(referencedAssembly))
                                _referenceAssembly.Add(referencedAssembly);
                            refAssemblies.Add(referencedAssembly);
                        }
                        catch (Exception ex)
                        {
                            ConsoleC.WriteLine(ex,"GetReferenceAssembly(params string[] virtualPaths) error " + referencedAssemblyFile);
                        }
                    }
                    result = existsPath ? refAssemblies : _referenceAssembly;
                });
            }
            return result;
        }

        private static List<Assembly> GetSystemModules()
        {
            var assemblies = new List<Assembly>();
            var referenceAssemblies = GetReferenceAssembly();
            foreach (var referenceAssembly in referenceAssemblies)
            {
                var abstractModules = GetAbstractModules(referenceAssembly);
                if (abstractModules.Any(p => p.GetType().IsSubclassOf(typeof(SystemModule))))
                {
                    assemblies.Add(referenceAssembly);
                }
            }
            return assemblies;
        }

        private static List<Assembly> GetAssemblies(params string[] virtualPaths)
        {
            var referenceAssemblies = new List<Assembly>();
            if (virtualPaths.Any())
            {
                referenceAssemblies = GetReferenceAssembly(virtualPaths);
            }
            else
            {
                var assemblyNames = GetDefaultAssemblyNames();//?.Select(p => p.Name).ToArray();
                assemblyNames = GetFilterAssemblies(assemblyNames);
                foreach (var name in assemblyNames)
                {
                    try
                    {
                        if (referenceAssemblies.Find(f => f.GetName().Name == name.Name) == null)
                            referenceAssemblies.Add(Assembly.Load(name));
                    }
                    catch (Exception ex)
                    {
                        ConsoleC.WriteLine(ex, "GetAssemblies(params string[] virtualPaths) error " + name.FullName);
                    }
                }
                _referenceAssembly.AddRange(referenceAssemblies.Except(_referenceAssembly));
            }
            return referenceAssemblies;
        }
        private static IEnumerable<AssemblyName> GetDefaultAssemblyNames()
        {
            //AppDomain.CurrentDomain.SetData("APP_CONTEXT_DEPS_FILES", AppContext.BaseDirectory+ "CNative.Services.Server.deps.json");
            if (DependencyContext.Default == null)
            {
                var refAssemblyNames = new List<AssemblyName>();
                //----------------------------------------------------------------------------------------------------
                var assemblyFiles = GetAllAssemblyFiles(Cloud.CPlatform.Utilities.EnvironmentHelper.BaseDirectory);
                foreach (var referencedAssemblyFile in assemblyFiles)
                {
                    try
                    {
                        var referencedAssembly = Assembly.LoadFrom(referencedAssemblyFile);
                        if (refAssemblyNames.Find(f => f.Name == referencedAssembly.GetName().Name) == null)
                            refAssemblyNames.Add(referencedAssembly.GetName());
                    }
                    catch (Exception ex)
                    {
                        ConsoleC.WriteLine(ex, "GetDefaultAssemblyNames() error "+ referencedAssemblyFile);
                    }
                }
                //----------------------------------------------------------------------------------------------------
                var assemblies = AppDomain.CurrentDomain.GetAssemblies();
                foreach (var a in assemblies)
                {
                    if (refAssemblyNames.Find(f => f.Name == a.GetName().Name) == null)
                        refAssemblyNames.Add(a.GetName());

                    var aa = a.GetReferencedAssemblies();
                    foreach (var sas in aa)
                    {
                        if (refAssemblyNames.Find(f => f.Name == sas.Name) == null)
                            refAssemblyNames.Add(sas);
                    }
                }
                              
                return refAssemblyNames;
            }
            else
            {
                return DependencyContext.Default.GetDefaultAssemblyNames();
            }
        }
        /// <summary>
        /// 获取抽象模块（查找继承AbstractModule类的对象并创建实例）
        /// </summary>
        /// <param name="assembly"></param>
        /// <returns></returns>
        private static List<AbstractModule> GetAbstractModules(Assembly assembly)
        {
            var abstractModules = new List<AbstractModule>();
            Type[] arrayModule =
                assembly.GetTypes().Where(
                    t => t.IsSubclassOf(typeof(AbstractModule))).ToArray();
            foreach (var moduleType in arrayModule)
            {
                var abstractModule = (AbstractModule)Activator.CreateInstance(moduleType);
                abstractModules.Add(abstractModule);
            }
            return abstractModules;
        }

        //private static string[] GetFilterAssemblies(string[] assemblyNames)
        //{
        //    var notRelatedFile = AppConfig.ServerOptions.NotRelatedAssemblyFiles;
        //    var relatedFile = AppConfig.ServerOptions.RelatedAssemblyFiles;
        //    var pattern = string.Format("^Microsoft.\\w*|^System.\\w*|^DotNetty.\\w*|^runtime.\\w*|^ZooKeeperNetEx\\w*|^StackExchange.Redis\\w*|^Consul\\w*|^Newtonsoft.Json.\\w*|^Autofac.\\w*{0}",
        //       string.IsNullOrEmpty(notRelatedFile) ? "" : $"|{notRelatedFile}");
        //    Regex notRelatedRegex = new Regex(pattern, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
        //    Regex relatedRegex = new Regex(relatedFile, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
        //    if (!string.IsNullOrEmpty(relatedFile))
        //    {
        //        return
        //            assemblyNames.Where(
        //                name => !notRelatedRegex.IsMatch(name) && relatedRegex.IsMatch(name)).ToArray();
        //    }
        //    else
        //    {
        //        return
        //            assemblyNames.Where(
        //                name => !notRelatedRegex.IsMatch(name)).ToArray();
        //    }
        //}
        private static IEnumerable<AssemblyName> GetFilterAssemblies(IEnumerable<AssemblyName> assemblyNames)
        {
            var notRelatedFile = AppConfig.ServerOptions.NotRelatedAssemblyFiles;
            var relatedFile = AppConfig.ServerOptions.RelatedAssemblyFiles;
            var pattern = string.Format("^Microsoft.\\w*|^System.\\w*|^DotNetty.\\w*|^runtime.\\w*|^ZooKeeperNetEx\\w*"
                + "|^StackExchange.Redis\\w*|^Consul\\w*|^Newtonsoft.Json.\\w*|^Autofac.\\w*{0}",
               string.IsNullOrEmpty(notRelatedFile) ? "" : $"|{notRelatedFile}");
            Regex notRelatedRegex = new Regex(pattern, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
            Regex relatedRegex = new Regex(relatedFile, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
            if (!string.IsNullOrEmpty(relatedFile))
            {
                return
                    assemblyNames.Where(
                        name => !notRelatedRegex.IsMatch(name.Name) && relatedRegex.IsMatch(name.Name)).ToArray();
            }
            else
            {
                return
                    assemblyNames.Where(
                        name => !notRelatedRegex.IsMatch(name.Name)).ToArray();
            }
        }

        private static List<string> GetAllAssemblyFiles(string parentDir)
        {
            var notRelatedFile = AppConfig.ServerOptions.NotRelatedAssemblyFiles;
            var relatedFile = AppConfig.ServerOptions.RelatedAssemblyFiles;
            var pattern = string.Format("^Microsoft.\\w*|^System.\\w*|^Netty.\\w*|^Autofac.\\w*|^libSkiaSharp.\\w*|^libuv.\\w*|^grpc_csharp_ext.\\w*{0}",
               string.IsNullOrEmpty(notRelatedFile) ? "" : $"|{notRelatedFile}");
            Regex notRelatedRegex = new Regex(pattern, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
            Regex relatedRegex = new Regex(relatedFile, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
            if (!string.IsNullOrEmpty(relatedFile))
            {
                return
                    Directory.GetFiles(parentDir, "*.dll").Select(Path.GetFullPath).Where(
                        a => !notRelatedRegex.IsMatch(Path.GetFileName(a)) && relatedRegex.IsMatch(Path.GetFileName(a))).ToList();
            }
            else
            {
                return
                    Directory.GetFiles(parentDir, "*.dll").Select(Path.GetFullPath).Where(
                        a => !notRelatedRegex.IsMatch(Path.GetFileName(a))).ToList();
            }
        }

    }
    public static class ConsoleC
    {
        /// <summary>
        /// Console 扩展方法
        /// </summary>
        /// <param name="value"></param>
        /// <param name="consoleColor"></param>
        public static void WriteLine(string msg, ConsoleColor consoleColor = ConsoleColor.Red)
        {
            var cl = System.Console.ForegroundColor;
            System.Console.ForegroundColor = consoleColor;
            System.Console.WriteLine(msg);
            System.Console.ForegroundColor = cl;
            System.Console.WriteLine("-------------------------------------------------------------------------------");
        }
        /// <summary>
        /// Console 扩展方法
        /// </summary>
        /// <param name="value"></param>
        /// <param name="consoleColor"></param>
        public static void WriteLine(Exception ex, string msg = "", ConsoleColor consoleColor = ConsoleColor.Red)
        {
            WriteLine(msg + " " + ex?.GetExceptionMessage(), consoleColor);
        }
    }
}